#include "protobuf/codec/codec.h"
#include "protobuf/codec/dispatcher.h"
#include "muduo/base/Logging.h"
#include "muduo/base/Mutex.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/TcpServer.h"

#include <iostream>
#include <functional>


class Server{
public:
//创建指针指针方便后面使用
typedef std::shared_ptr<request::TranslateRequest> TranslateRequestPtr;
typedef std::shared_ptr<request::AddRequest> AddRequestPtr;
typedef std::shared_ptr<google::protobuf::Message> MessagePtr;

Server(uint16_t port):_server(&_baseloop,muduo::net::InetAddress("0.0.0.0",port),"TcpServer"),
    _dispatcher(std::bind(&Server::onUnknownMessage,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3)),
    _codec(std::bind(&ProtobufDispatcher::onProtobufMessage,&_dispatcher,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3))
    {
      //给dispatcher内部注册请求处理函数:
      
      //1. 如当监听到Translate请求后就会执行该函数
      _dispatcher.registerMessageCallback<request::TranslateRequest>(std::bind(&Server::onTranslate,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
      //2. .... 
      _dispatcher.registerMessageCallback<request::AddRequest>(std::bind(&Server::onAdd,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));

      //再给server 注册处理函数 ； 连接事件就绪 / 正常事件就绪

      //连接就绪：
      _server.setConnectionCallback(std::bind(&Server::onConnection,this,std::placeholders::_1));

      //事件就绪：
      //对于绑定ProtobufCodec里面的onMessage函数，是因为需要进行数据的序列化操作，所以使用Protobuf
      _server.setMessageCallback(std::bind(&ProtobufCodec::onMessage,&_codec,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3));
    }

    void start()
    {
      //启动服务器
      _server.start();
      //开启循环监听
      _baseloop.loop();
    }
private:
//未知事件就绪：
  void onUnknownMessage(const muduo::net::TcpConnectionPtr& conn,
                        const MessagePtr& message,
                        muduo::Timestamp)
  {
    LOG_INFO << "onUnknownMessage: " << message->GetTypeName();
    conn->shutdown();
  }

  std::string Translate(std::string english){
        std::unordered_map<std::string,std::string> dict_map = {
            {"apple","苹果"},
            {"hello","你好"}
        };      
        // for(auto k : dict_map)
        //     std::cout << k.first << std::endl;

        std::cout <<"eglish:" << english << std::endl; 
        // english.resize(english.size() - strlen("\n"));//注意tcp协议中粘包问题的\r\n，需要把\r\n字符去除，才能算原本的字符串也才能正确的判断
        auto iter = dict_map.find(english);
        
        if(iter == dict_map.end())
        {
            return "查不到此单词\n";
        }

        return iter->second + "\n";
    } 
  void onTranslate(const muduo::net::TcpConnectionPtr& conn,const TranslateRequestPtr& message,muduo::Timestamp){
    std::string req = message->msg();
    std::string translate_res = Translate(req);

    request::TranslateResponse resp;
    resp.set_msg(translate_res);
    _codec.send(conn,resp);
  }

  void onAdd(const muduo::net::TcpConnectionPtr& conn,const AddRequestPtr& message,muduo::Timestamp){
    uint32_t num1 = message->num1();
    uint32_t num2 = message->num2();
    uint32_t result = num1 + num2;

    request::AddResponse resp;
    resp.set_result((uint32_t)result);
    _codec.send(conn,resp);
  }

  void onConnection(const muduo::net::TcpConnectionPtr &conn){
        if(!conn->connected())
        {
            std::cout << "新连接关闭" << std::endl;
        }
        else
        {
            std::cout << "新连接成功" << std::endl;
        }   
  }

private:
    ProtobufDispatcher _dispatcher;
    ProtobufCodec _codec;
    muduo::net::EventLoop _baseloop;
    muduo::net::TcpServer _server;
};

